package org.vectrics.common.util;


import org.apache.log4j.*;
import org.vectrics.SystemException;
import org.vectrics.hibernate.ThreadProperties;
import org.vectrics.recruiter.RecruitServiceLocator;

import javax.servlet.ServletContext;
import java.net.URL;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;



public class FileUtil  {
    private static final int DELETE_RETRY_SLEEP_MILLIS = 10;	
    public static String VECTRICS_CONTENT_BEGIN_TAG = "<!--VECTRICS-BEGIN-->";
    public static String VECTRICS_CONTENT_END_TAG = "<!--VECTRICS-END-->";
    
    private static Category log = Category.getInstance(FileUtil.class);

    public static String getWebFileContents(String filePath, ServletContext servletContext) {
        
        if (log.isDebugEnabled())
            log.debug("getFileContents() called with path = " + filePath);

        String content = null;

        if (log.isDebugEnabled())
            log.debug("getFileContents() - after replaceContentProperties() - file = " + filePath);

        if (filePath != null) {
            StringBuffer str = new StringBuffer();
            InputStream input = null;
            try {
                URL url = new URL(filePath);
                input = url.openStream();
            }
            catch (java.net.MalformedURLException me) {
                log.error("Illegal URL: " + filePath + "  Exception thrown.", me);
            }
            catch (java.io.IOException ie) {
                log.error("IOException loading: " + filePath + "  Exception thrown.", ie);
            }
            
            if (input == null) {
                str.append("<b>Could not load: " + filePath + "<b>");
                log.error("Could not load: " + filePath + "  - getFileContents()");
            }
            else {

                try {

                    int c;
                    do {
                        c = input.read();
                        if (c != -1)
                            str.append((char)c);
                    } while (c != -1);

                    input.close();
                }
                catch (Exception ex) {
                    str.append(ex.getMessage());
                    log.error("Exception loading: " + filePath, ex);
                };
            }
            content = str.toString();
            
            // Html files may be included that have a section within that is to 
            // be extracted without all the header tags, etc.  This is done so that
            // html files can be edited in a visual tool and part added to an overall
            // template.
            if (filePath.indexOf("htm") > 0)
                content = extractVectricsContent(content, filePath);
        }
        else {
            content = null;
            log.error("getFileContents() - filePath was null.");
        }
        return(content);
    }
    
    public static String getContentFromStream(InputStream input) {
    	StringBuffer str = new StringBuffer();
    	try {

            int c;
            do {
                c = input.read();
                if (c != -1)
                    str.append((char)c);
            } while (c != -1);

            input.close();
        }
        catch (Exception ex) {
            str.append(ex.getMessage());
            log.error("Exception loading from stream", ex);
        };
    	return(str.toString());
    }
    
    public static void createDirectoryIfNotExist(String indexPath) {
    	File file = new File(indexPath);
    	if (file.exists()) {
    		if (file.isDirectory()) {
        		log.debug("Directory already exists, no action needed");
    		} else if (file.isFile()) {
    			throw new SystemException("File exists with same path as requested new directory: " + indexPath);
    		} else {
    			throw new SystemException("Path exists, but is neither file nor directory");
    		}
    	} else {
    		file.mkdirs();
    	}
    }
    
    public static void saveContentToFile(String fileName, String content) {
    	deleteFileIfExists(fileName);
    	try {
    		FileOutputStream fileOutputStream = new FileOutputStream(fileName);
    		
    		fileOutputStream.write(content.getBytes());
    		
    		fileOutputStream.close();
    	} catch (Exception ex) {
    		throw new SystemException("Exception saving content to file: " + fileName);
    	}
    }
    
    public static void deleteFileIfExists(String fileName) {
    	File file = new File(fileName);
    	if (file.exists()) {
    		file.delete();
    	}
    }
    
    public static String getFileContents(String filePath)
    {
        String content = null;
    	try {
	        if (log.isDebugEnabled())
	            log.debug("getFileContents() called with path = " + filePath);
	
	
	
	        if (filePath != null) {
	            StringBuffer str = new StringBuffer();
	            FileInputStream input = new FileInputStream(filePath);
	            
	            if (input == null) {
	                str.append("<b>Could not load: " + filePath + "<b>");
	                log.error("Could not load: " + filePath + "  - getFileContents()");
	            }
	            else {
	
	                try {
	
	                    int c;
	                    do {
	                        c = input.read();
	                        if (c != -1)
	                            str.append((char)c);
	                    } while (c != -1);
	
	                    input.close();
	                }
	                catch (Exception ex) {
	                    str.append(ex.getMessage());
	                    log.error("Exception loading: " + filePath, ex);
	                };
	            }
	            content = str.toString();
	            
	            // Html files may be included that have a section within that is to 
	            // be extracted without all the header tags, etc.  This is done so that
	            // html files can be edited in a visual tool and part added to an overall
	            // template.
	            if (filePath.indexOf("htm") > 0)
	                content = extractVectricsContent(content, filePath);
	        }
	        else {
	            content = null;
	            log.error("getFileContents() - filePath was null.");
	        }
    	}
    	catch (Throwable t) {
    		log.debug("Exception in getFileContents() - file = " + filePath, t);
    		throw new SystemException("Exception in getFileContents() - file = " + filePath, t);
    	}
        return(content);
    };
    
    public static String getServletFileContents(String filePath, ServletContext servletContext)
    {
        if (log.isDebugEnabled())
            log.debug("getFileContents() called with path = " + filePath);

        String content = null;

        

        if (filePath != null) {
            StringBuffer str = new StringBuffer();
            InputStream input = null;
            input = servletContext.getResourceAsStream(filePath);
            
            if (input == null) {
                str.append("<b>Could not load: " + filePath + "<b>");
                log.error("Could not load: " + filePath + "  - getFileContents()");
            }
            else {

                try {

                    int c;
                    do {
                        c = input.read();
                        if (c != -1)
                            str.append((char)c);
                    } while (c != -1);

                    input.close();
                }
                catch (Exception ex) {
                    str.append(ex.getMessage());
                    log.error("Exception loading: " + filePath, ex);
                };
            }
            content = str.toString();
            
            // Html files may be included that have a section within that is to 
            // be extracted without all the header tags, etc.  This is done so that
            // html files can be edited in a visual tool and part added to an overall
            // template.
            if (filePath.indexOf("htm") > 0)
                content = extractVectricsContent(content, filePath);
        }
        else {
            content = null;
            log.error("getFileContents() - filePath was null.");
        }
        return(content);
    };
    
    
    public static String extractVectricsContent(String beforeContent, String fileName) {
        log.debug("extractVectricsContent() called.");
        String content = null;
        int pos1 = beforeContent.indexOf(VECTRICS_CONTENT_BEGIN_TAG);
        if (pos1 >= 0) {
            int pos2 = beforeContent.indexOf(VECTRICS_CONTENT_END_TAG);
            if (pos2 < 0) {
                log.error("extractVectricsContent() - found tag:" + VECTRICS_CONTENT_BEGIN_TAG + " but could not find end tag for Vectrics content for file: " + fileName);
                content = "<h1>Found tag:" + VECTRICS_CONTENT_BEGIN_TAG + " but could not find end tag for Vectrics content for file: " + fileName +"</h1>"
                        + beforeContent.substring(pos1 + VECTRICS_CONTENT_BEGIN_TAG.length() + 1);                 
            }
            else {
                content = beforeContent.substring(pos1 + VECTRICS_CONTENT_BEGIN_TAG.length() + 1, pos2 - 1);                 
            }
        }
        else {
            log.debug("extractVectricsContent() - no vectrics tags found, using entire file.");
            
            content = beforeContent;
        }
        return(content);
    }
    
    
	static public void saveInputStreamToFile(InputStream inputStream, String targetFileName) {
		if (inputStream == null)
			throw new SystemException("inputStream was passed as null");
		
		
		try {
			File file = new File(targetFileName);
			if (file.exists()) {
				file.delete();
			}
		} catch (Exception ex) {
			log.error("Exception deleting existing file", ex);
		}
		
		try {
			FileOutputStream fileStream = new FileOutputStream(targetFileName);
			int word = 0;
			boolean done = false;
			while (!done) {
				word = inputStream.read();
				if (word >= 0) {
					fileStream.write(word);
				}
				else {
					done = true;
				}
			}
		} catch (Exception ex) {
			throw new SystemException("Exception saving input stream to new file: " + targetFileName, ex);
		}
	}
	
	public static String extractFileNameFromPath(String fileNameAndPath) {
		String fileName = fileNameAndPath;
		int indexFS = fileNameAndPath.lastIndexOf('/');
		int indexBS = fileNameAndPath.lastIndexOf('\\');
		int index = -1;
		if ((indexFS > 0) && (indexFS > indexBS)) {
			index = indexFS;
		} else if (indexBS > indexFS) {
			index = indexBS;
		}
		if (index > 0) {
			fileName = fileNameAndPath.substring(index + 1);
		}
		return(fileName);
	}
	
	
	/*
	 * Find the extention of the file name (without the '.').
	 */
	public static String findFileExtention(String fileName) {
		String extension = null;
		int indexOfLastPeriod = fileName.lastIndexOf(".");
		if (indexOfLastPeriod > 0 ) {
			extension = fileName.substring(indexOfLastPeriod + 1);
		}
		return(extension);
	}

	
	  static public boolean deleteDirectory(String path) {
		  File file = new File(path);
		  return deleteDirectory(file, false);
	  }

	  static public boolean deleteDirectory(File d, boolean isWindows) {
        String[] list = d.list();
        if (list == null) {
            list = new String[0];
        }
        for (int i = 0; i < list.length; i++) {
            String s = list[i];
            File f = new File(d, s);
        if (f.isDirectory()) {
            deleteDirectory(f, isWindows);
        } else {
            log.info("Deleting " + f.getAbsolutePath());
            if (!deleteFile(f, isWindows)) {
                String message = "Unable to delete file "
                    + f.getAbsolutePath();
                    throw new SystemException(message);
            }
        }
        }
        log.info("Deleting directory " + d.getAbsolutePath());
        if (!deleteDirectory(d, isWindows)) {
            String message = "Unable to delete directory "
                + d.getAbsolutePath();
            throw new SystemException(message);
        }
        return(true);
    }

    public static boolean deleteFile(File f, boolean isWindows) {
        if (!f.delete()) {
            if (isWindows) {
                System.gc();
            }
            try {
                Thread.sleep(DELETE_RETRY_SLEEP_MILLIS);
            } catch (InterruptedException ex) {
                // Ignore Exception
            }
            if (!f.delete()) {
                return false;
            }
        }
        return true;
    }
    
	    /**
	     * Compare the contents of two files to determine if they are equal or not.
	     *
	     * @param file1 the first file
	     * @param file2 the second file
	     * @return true if the content of the files are equal or they both don't exist, false otherwise
	     */
	    public boolean contentEquals( final File file1, final File file2 )
	        throws IOException
	    {
	        final boolean file1Exists = file1.exists();
	        if( file1Exists != file2.exists() )
	        {
	            return false;
	        }

	        if( !file1Exists )
	        {
	            // two not existing files are equal
	            return true;
	        }

	        if( file1.isDirectory() || file2.isDirectory() )
	        {
	            // don't want to compare directory contents
	            return false;
	        }

	        InputStream input1 = null;
	        InputStream input2 = null;
	        try
	        {
	            input1 = new FileInputStream( file1 );
	            input2 = new FileInputStream( file2 );
	            return contentEquals( input1, input2 );

	        }
	        finally
	        {
	            shutdownStream( input1 );
	            shutdownStream( input2 );
	        }
	    }	  
	    
	    /**
	     * Compare the contents of two Streams to determine if they are equal or not.
	     *
	     * @param input1 the first stream
	     * @param input2 the second stream
	     * @return true if the content of the streams are equal or they both don't exist, false otherwise
	     */
	    public static boolean contentEquals( final InputStream input1,
	                                   final InputStream input2 )
	        throws IOException
	    {
	        final InputStream bufferedInput1 = new BufferedInputStream( input1 );
	        final InputStream bufferedInput2 = new BufferedInputStream( input2 );

	        int count = 0;
	        int ch = bufferedInput1.read();
	        while( -1 != ch )
	        {
	            final int ch2 = bufferedInput2.read();
	            count++;
	            if( ch != ch2 )
	            {
	                System.out.println( "count = " + count );
	                System.out.println( "ch2 = " + ch2 );
	                System.out.println( "ch = " + ch );
	                return false;
	            }
	            ch = bufferedInput1.read();
	        }

	        final int ch2 = bufferedInput2.read();
	        if( -1 != ch2 )
	        {
	            return false;
	        }
	        else
	        {
	            return true;
	        }
	    }

	    public static void shutdownStream( final InputStream input )
	    {
	        if( null == input )
	        {
	            return;
	        }

	        try
	        {
	            input.close();
	        }
	        catch( final IOException ioe )
	        {
	        }
	    }

	    public static void shutdownStream( final OutputStream output )
	    {
	        if( null == output )
	        {
	            return;
	        }

	        try
	        {
	            output.close();
	        }
	        catch( final IOException ioe )
	        {
	        }
	    }

	    
	    // Valida que el nombre del archivo sea correcto.
		public static boolean isValidName(String name) {
			if ((name.indexOf("/")!=-1) || (name.indexOf("\\")!=-1)){
				return false;
			}
			boolean resultado = false;
			String ext = RecruitServiceLocator.getRecruitConfiguration()
  			                    .getCandidateDocumentPath(ThreadProperties.getDomain());
			File file = new File(ext + "/" + name);
			try {
				resultado = file.createNewFile();
			} catch (Exception e) {
				resultado = false;
				e.printStackTrace();
			}
			if (resultado) {
				file.delete();
			}
			return resultado;
		}	    
}


